package com.eas.task.examStatistic;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.eas.biz.constants.BizConstants;
import com.eas.biz.dao.statistic.dataobject.SchoolGradeStatisticDO;
import com.eas.biz.dao.statistic.dataobject.SchoolStatisticDO;
import com.eas.biz.dao.statistic.dataobject.SchoolStatisticQuery;
import com.eas.biz.dao.statistic.interfaces.SchoolGradeStatisticDao;
import com.eas.biz.dao.statistic.interfaces.SchoolStatisticDao;
import com.eas.biz.dao.user.dataobject.ClassDO;
import com.eas.biz.dao.user.dataobject.ClassQuery;
import com.eas.biz.service.statistic.domain.GradeLevelCount;
import com.eas.biz.service.user.domain.SchoolInfo;
import com.eas.biz.service.user.interfaces.ClassService;
import com.eas.biz.service.user.interfaces.SchoolService;
import com.eas.task.common.util.DoubleUtil;
import com.eas.task.common.util.SubjectUtil;
import com.eas.task.examStatistic.dto.CombinationSubjectCounter;
import com.eas.task.examStatistic.dto.GradeCounter;
import com.eas.task.examStatistic.dto.TaskGradeLevelCount;

public class SchoolStatisticJob implements ApplicationContextAware {

    public static final String JOB_TARGET = "school";

    @Resource(name = "schoolService")
    private SchoolService schoolService;

    @Resource(name = "classService")
    private ClassService classService;

    @Autowired
    private SchoolStatisticDao schoolStatisticDao;

    @Autowired
    private SchoolGradeStatisticDao schoolGradeStatisticDao;

    private ApplicationContext context;

    private long schoolId;

    private long examId;

    private SchoolInfo schoolInfo;

    public void work() {
        if (schoolInfo == null) {
            schoolInfo = schoolService.getSchoolInfo(schoolId);
        }
        Map<String, GradeCounter> schoolCounter = new HashMap<String, GradeCounter>();
        CombinationSubjectCounter counter = null;

        List<ClassDO> classList = getClassList();
        if (classList == null || classList.size() == 0) {
            return;
        }

        for (ClassDO classDO : classList) {
            ClassStatisticJob job = (ClassStatisticJob) context.getBean("classStatisticJob");
            job.setExamId(examId);
            job.setSchoolId(schoolId);
            job.setClassId(classDO.getId());
            job.work();
            Map<String, GradeCounter> classCounter = job.getSubjectMap();
            if (classCounter != null && classCounter.size() > 0) {
                for (Map.Entry<String, GradeCounter> entry : classCounter.entrySet()) {
                    String subject = entry.getKey();
                    GradeCounter schoolSubjectCounter = schoolCounter.get(subject);
                    if (schoolSubjectCounter == null) {
                        schoolSubjectCounter = new GradeCounter();
                        schoolCounter.put(subject, schoolSubjectCounter);
                    }
                    schoolSubjectCounter.merge(entry.getValue());
                }
            }

            CombinationSubjectCounter classCombinationCounter = job.getCombinationCounter();
            if (classCombinationCounter != null) {
                if (counter == null) {
                    counter = new CombinationSubjectCounter();
                    counter.setMainSubject(BizConstants.TOTAL_SCORE_SUBJECT);
                }
                counter.mergeCounter(classCombinationCounter);
            }

            job.clear();
        }

        if (schoolCounter.size() > 0) {
            saveCommonStatistic(schoolCounter);
            saveCombinationStatistic(counter, schoolCounter);
        }

        // System.out.println("school process finished: " + schoolId);
    }

    private void saveCombinationStatistic(CombinationSubjectCounter counter,
            Map<String, GradeCounter> schoolCounter) {
        if (counter == null) {
            return;
        }

        String mainSubject = counter.getMainSubject();
        GradeCounter mainCounter = schoolCounter.get(mainSubject);
        Map<String, List<TaskGradeLevelCount>> subjectMap = counter.getSubjectMap();
        if (subjectMap.size() == 0) {
            return;
        }

        for (Entry<String, List<TaskGradeLevelCount>> entry : subjectMap.entrySet()) {
            List<TaskGradeLevelCount> list = entry.getValue();
            if (list == null || list.size() == 0) {
                continue;
            }

            SchoolStatisticDO ssDO = new SchoolStatisticDO();
            ssDO.setSchoolId(schoolId);
            ssDO.setAreaId(schoolInfo.getAreaId());
            ssDO.setExamId(examId);
            ssDO.setSubject(SubjectUtil.getCombinationSubject(mainSubject, entry.getKey()));
            ssDO.setStudentCount(mainCounter.getStudentCount());
            ssDO.setMaxScore(mainCounter.getMaxScore());
            ssDO.setMinScore(mainCounter.getMinScore());
            ssDO.setAvgScore((float) DoubleUtil.round(mainCounter.getAvgScore(), 2));
            ssDO.setDiviation(DoubleUtil.round(mainCounter.getStandardDiviation(),
                    BizConstants.DIVIATION_DECIMAL_SCALE));
            schoolStatisticDao.insert(ssDO);

            for (GradeLevelCount gradeLevel : list) {
                SchoolGradeStatisticDO sgsDO = new SchoolGradeStatisticDO();
                sgsDO.setExamId(examId);
                sgsDO.setSchoolId(schoolId);
                sgsDO.setAreaId(schoolInfo.getAreaId());
                sgsDO.setSubject(SubjectUtil.getCombinationSubject(mainSubject, entry.getKey()));
                sgsDO.setLevel(gradeLevel.getLevel());
                sgsDO.setScore(gradeLevel.getScore());
                sgsDO.setCount(gradeLevel.getCount());
                schoolGradeStatisticDao.insert(sgsDO);
            }
        }

    }

    private void saveCommonStatistic(Map<String, GradeCounter> schoolCounter) {
        SchoolStatisticQuery query = new SchoolStatisticQuery(null);
        query.setSchoolId(schoolId);
        query.setExamId(examId);
        schoolStatisticDao.deleteByQuery(query);
        schoolGradeStatisticDao.deleteByQuery(query);

        for (Map.Entry<String, GradeCounter> entry : schoolCounter.entrySet()) {
            GradeCounter counter = entry.getValue();
            SchoolStatisticDO ssDO = new SchoolStatisticDO();
            ssDO.setSchoolId(schoolId);
            ssDO.setAreaId(schoolInfo.getAreaId());
            ssDO.setExamId(examId);
            ssDO.setSubject(entry.getKey());
            ssDO.setStudentCount(counter.getStudentCount());
            ssDO.setMaxScore(counter.getMaxScore());
            ssDO.setMinScore(counter.getMinScore());
            ssDO.setAvgScore((float) DoubleUtil.round(counter.getAvgScore(), 2));
            ssDO.setDiviation(DoubleUtil.round(counter.getStandardDiviation(),
                    BizConstants.DIVIATION_DECIMAL_SCALE));
            schoolStatisticDao.insert(ssDO);

            for (GradeLevelCount gradeLevel : counter.getGradeCountList()) {
                SchoolGradeStatisticDO sgsDO = new SchoolGradeStatisticDO();
                sgsDO.setExamId(examId);
                sgsDO.setSchoolId(schoolId);
                sgsDO.setAreaId(schoolInfo.getAreaId());
                sgsDO.setSubject(entry.getKey());
                sgsDO.setLevel(gradeLevel.getLevel());
                sgsDO.setScore(gradeLevel.getScore());
                sgsDO.setCount(gradeLevel.getCount());
                schoolGradeStatisticDao.insert(sgsDO);
            }
        }
    }

    private List<ClassDO> getClassList() {
        ClassQuery query = new ClassQuery();
        query.setSchoolId(schoolId);
        query.setStatus("1");
        return classService.selectByQuery(query);
    }

    public long getSchoolId() {
        return schoolId;
    }

    public void setSchoolId(long schoolId) {
        this.schoolId = schoolId;
    }

    public long getExamId() {
        return examId;
    }

    public void setExamId(long examId) {
        this.examId = examId;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

}
